package be.novelfaces.test.common;

import static org.easymock.EasyMock.expect;

import java.util.HashMap;
import java.util.Map;

import javax.faces.component.UIComponent;
import javax.faces.component.UIViewRoot;

import org.jboss.test.faces.mock.MockFacesEnvironment;
import org.junit.After;
import org.junit.Before;

import be.novelfaces.component.util.RenderUtils;
import be.novelfaces.component.util.RenderUtilsFactoryForTests;

public abstract class AbstractMockFacesTestCase<T extends UIComponent> {
	private MockFacesEnvironment environment;
	private T uiComponentMock;
	private UIViewRoot uiViewRootMock;
	private Map<String, Object> attributesMap;
	private RenderUtils renderUtilsMock;

	@Before
	public void setUp() throws Exception {
		// create mock environment
		environment = MockFacesEnvironment.createEnvironment();

		if (getUIComponentClass() != null) {
			// create mock component
			uiComponentMock = environment.createMock(getUIComponentClass());
		}
		uiViewRootMock = environment.createMock(UIViewRoot.class);

		// set up attributes map
		attributesMap = new HashMap<String, Object>();
		expect(uiComponentMock.getAttributes())
				.andStubReturn(attributesMap);

		renderUtilsMock = RenderUtilsFactoryForTests
				.setMockAsInstance(getEnvironment());

		extraSetUp();
	}

	protected abstract Class<T> getUIComponentClass();

	protected void extraSetUp() throws Exception {
		// hook for subclasses
	}

	@After
	public void tearDown() throws Exception {
		// do verification for mocked objects
		environment.verify();

		// do clean up
		environment.release();
		environment = null;

		uiComponentMock = null;
		attributesMap = null;
		RenderUtilsFactoryForTests.resetInstance();
		extraTearDown();
	}

	protected void extraTearDown() {
		// hook for subclasses
	}

	public MockFacesEnvironment getEnvironment() {
		return environment;
	}

	public T getUiComponentMock() {
		return uiComponentMock;
	}

	public Map<String, Object> getAttributesMap() {
		return attributesMap;
	}

	public UIViewRoot getUiViewRootMock() {
		return uiViewRootMock;
	}

	public RenderUtils getRenderUtilsMock() {
		return renderUtilsMock;
	}

}